#pragma once
#include <QtCore/QObject>
#include "CharacterModel.h"
#include "SkillListVM.h"
#include "ExtraordinaryAbilityListVM.h"
#include "WeaponProficiencyListVM.h"
#include "EquipmentListVM.h"

class QDomDocument;

class CharacterVM :
	public QObject
{
	Q_OBJECT
	Q_PROPERTY(QString Name READ Name WRITE setName NOTIFY NameChanged)
	Q_PROPERTY(QString Alignment READ Alignment WRITE setAlignment NOTIFY AlignmentChanged)
	Q_PROPERTY(QString Occupation READ Occupation WRITE setOccupation NOTIFY OccupationChanged)
	Q_PROPERTY(QString Type READ Type WRITE setType NOTIFY TypeChanged)
	Q_PROPERTY(QPixmap Image READ Image NOTIFY ImageChanged STORED false)
	Q_PROPERTY(int IQ READ IQ WRITE setIQ NOTIFY IQChanged)
	Q_PROPERTY(int ME READ ME WRITE setME NOTIFY MEChanged)
	Q_PROPERTY(int MA READ MA WRITE setMA NOTIFY MAChanged)
	Q_PROPERTY(int PS READ PS WRITE setPS NOTIFY PSChanged)
	Q_PROPERTY(int PP READ PP WRITE setPP NOTIFY PPChanged)
	Q_PROPERTY(int PE READ PE WRITE setPE NOTIFY PEChanged)
	Q_PROPERTY(int PB READ PB WRITE setPB NOTIFY PBChanged)
	Q_PROPERTY(int SPD READ SPD WRITE setSPD NOTIFY SPDChanged)
	Q_PROPERTY(int HP READ HP WRITE setHP NOTIFY HPChanged)
	Q_PROPERTY(int SDC READ SDC WRITE setSDC NOTIFY SDCChanged)
	Q_PROPERTY(QString HandToHandType READ HandToHandType WRITE setHandToHandType NOTIFY HandToHandTypeChanged)
	Q_PROPERTY(int NumAttacks READ NumAttacks WRITE setNumAttacks NOTIFY NumAttacksChanged)
	Q_PROPERTY(int Strike READ Strike WRITE setStrike NOTIFY StrikeChanged)
	Q_PROPERTY(int Damage READ Damage WRITE setDamage NOTIFY DamageChanged)
	Q_PROPERTY(int Kick READ Kick WRITE setKick NOTIFY KickChanged)
	Q_PROPERTY(int Parry READ Parry WRITE setParry NOTIFY ParryChanged)
	Q_PROPERTY(int Roll READ Roll WRITE setRoll NOTIFY RollChanged)
	Q_PROPERTY(int Dodge READ Dodge WRITE setDodge NOTIFY DodgeChanged)
	Q_PROPERTY(int Critical READ Critical WRITE setCritical NOTIFY CriticalChanged)
	Q_PROPERTY(int CurrentHP READ CurrentHP WRITE setCurrentHP NOTIFY CurrentHPChanged)
	Q_PROPERTY(int CurrentSDC READ CurrentSDC WRITE setCurrentSDC NOTIFY CurrentSDCChanged)
	Q_PROPERTY(QString Special READ Special WRITE setSpecial NOTIFY SpecialChanged)
	Q_PROPERTY(QString SaveBonus READ SaveBonus WRITE setSaveBonus NOTIFY SaveBonusChanged)
	Q_PROPERTY(QString Notes READ Notes WRITE setNotes NOTIFY NotesChanged)

#pragma region Constructor

public:
	CharacterVM();
	~CharacterVM(void);

#pragma endregion

#pragma region Properties

public:
	SkillListVM& PrimarySkills() { return _PrimarySkills; }
	SkillListVM& SecondarySkills() { return _SecondarySkills; }
	ExtraordinaryAbilityListVM& ExtraordinaryAbilities() { return _ExtraordinaryAbilities; }
	WeaponProficiencyListVM& WeaponProficiencies() { return _WeaponProficiencies; }
	EquipmentListVM& Equipment() { return _Equipment; }
	const SkillListVM& PrimarySkills() const { return _PrimarySkills; }
	const SkillListVM& SecondarySkills() const { return _SecondarySkills; }
	const ExtraordinaryAbilityListVM& ExtraordinaryAbilities() const { return _ExtraordinaryAbilities; }
	const WeaponProficiencyListVM& WeaponProficiencies() const { return _WeaponProficiencies; }
	const EquipmentListVM& Equipment() const { return _Equipment; }
	Q_VM_PROP_DECL(QString, Name)
	Q_VM_PROP_DECL(QString, Alignment)
	Q_VM_PROP_DECL(QString, Occupation)
	Q_VM_PROP_DECL(QString, Type)
	Q_VM_PROP_DECL(int, IQ)
	Q_VM_PROP_DECL(int, ME)
	Q_VM_PROP_DECL(int, MA)
	Q_VM_PROP_DECL(int, PS)
	Q_VM_PROP_DECL(int, PP)
	Q_VM_PROP_DECL(int, PE)
	Q_VM_PROP_DECL(int, PB)
	Q_VM_PROP_DECL(int, SPD)
	Q_VM_PROP_DECL(int, HP)
	Q_VM_PROP_DECL(int, SDC)
	Q_VM_PROP_DECL(QString, HandToHandType)
	Q_VM_PROP_DECL(int, NumAttacks)
	Q_VM_PROP_DECL(int, Strike)
	Q_VM_PROP_DECL(int, Damage)
	Q_VM_PROP_DECL(int, Kick)
	Q_VM_PROP_DECL(int, Parry)
	Q_VM_PROP_DECL(int, Roll)
	Q_VM_PROP_DECL(int, Dodge)
	Q_VM_PROP_DECL(int, Critical)
	Q_VM_PROP_DECL(int, CurrentHP)
	Q_VM_PROP_DECL(int, CurrentSDC)
	Q_VM_PROP_DECL(QString, Special)
	Q_VM_PROP_DECL(QString, SaveBonus)
	Q_VM_PROP_DECL(QString, Notes)
	QPixmap& Image()
	{
		QPixmap imgTmp;
		imgTmp.loadFromData(_model.Image());
		_Image = imgTmp.scaledToHeight(375, Qt::SmoothTransformation);
		return _Image;
	}
	const QByteArray ImageAsBytes() const { return _model.Image(); }

signals:
	void NameChanged(const QString& value);
	void AlignmentChanged(const QString& value);
	void OccupationChanged(const QString& value);
	void TypeChanged(const QString& value);
	void ImageChanged(const QPixmap& value);
	void IQChanged(const int& value);
	void MEChanged(const int& value);
	void MAChanged(const int& value);
	void PSChanged(const int& value);
	void PPChanged(const int& value);
	void PEChanged(const int& value);
	void PBChanged(const int& value);
	void SPDChanged(const int& value);
	void HPChanged(const int& value);
	void SDCChanged(const int& value);
	void HandToHandTypeChanged(const QString& value);
	void NumAttacksChanged(const int& value);
	void StrikeChanged(const int& value);
	void DamageChanged(const int& value);
	void KickChanged(const int& value);
	void ParryChanged(const int& value);
	void RollChanged(const int& value);
	void DodgeChanged(const int& value);
	void CriticalChanged(const int& value);
	void CurrentHPChanged(const int& value);
	void CurrentSDCChanged(const int& value);
	void SpecialChanged(const QString& value);
	void SaveBonusChanged(const QString& value);
	void NotesChanged(const QString& value);

public slots:
	void setName(const QString& value) { _model.setName(value); NameChanged(value); }
	void setAlignment(const QString& value) { _model.setAlignment(value); AlignmentChanged(value); }
	void setOccupation(const QString& value) { _model.setOccupation(value); OccupationChanged(value); }
	void setType(const QString& value) { _model.setType(value); TypeChanged(value); }
	void setIQ(const int& value) { _model.setIQ(value); IQChanged(value); }
	void setME(const int& value) { _model.setME(value); MEChanged(value); }
	void setMA(const int& value) { _model.setMA(value); MAChanged(value); }
	void setPS(const int& value) { _model.setPS(value); PSChanged(value); }
	void setPP(const int& value) { _model.setPP(value); PPChanged(value); }
	void setPE(const int& value) { _model.setPE(value); PEChanged(value); }
	void setPB(const int& value) { _model.setPB(value); PBChanged(value); }
	void setSPD(const int& value) { _model.setSPD(value); SPDChanged(value); }
	void setHP(const int& value) { _model.setHP(value); HPChanged(value); }
	void setSDC(const int& value) { _model.setSDC(value); SDCChanged(value); }
	void setHandToHandType(const QString& value) { _model.setHandToHandType(value); HandToHandTypeChanged(value); }
	void setNumAttacks(const int& value) { _model.setNumAttacks(value); NumAttacksChanged(value); }
	void setStrike(const int& value) { _model.setStrike(value); StrikeChanged(value); }
	void setDamage(const int& value) { _model.setDamage(value); DamageChanged(value); }
	void setKick(const int& value) { _model.setKick(value); KickChanged(value); }
	void setParry(const int& value) { _model.setParry(value); ParryChanged(value); }
	void setRoll(const int& value) { _model.setRoll(value); RollChanged(value); }
	void setDodge(const int& value) { _model.setDodge(value); DodgeChanged(value); }
	void setCritical(const int& value) { _model.setCritical(value); CriticalChanged(value); }
	void setCurrentHP(const int& value) { _model.setCurrentHP(value); CurrentHPChanged(value); }
	void setCurrentSDC(const int& value) { _model.setCurrentSDC(value); CurrentSDCChanged(value); }
	void setSpecial(const QString& value) { _model.setSpecial(value); SpecialChanged(value); }
	void setSaveBonus(const QString& value) { _model.setSaveBonus(value); SaveBonusChanged(value); }
	void setNotes(const QString& value) { _model.setNotes(value); NotesChanged(value); }
	void setImage(const QByteArray& value) 
	{ 
		_model.setImage(value); 
		ImageChanged(Image()); 
	}

private:
	SkillListVM _PrimarySkills;
	SkillListVM _SecondarySkills;
	ExtraordinaryAbilityListVM _ExtraordinaryAbilities;
	WeaponProficiencyListVM _WeaponProficiencies;
	EquipmentListVM _Equipment;
	QPixmap     _Image;

#pragma endregion

#pragma region Public Methods and Operators

public:
	bool Serialize(const QString& fileName);
	bool Deserialize(const QString& fileName);
	void CopyDataFrom(const CharacterVM& source);

#pragma endregion

#pragma region Helper Methods

private:
	void CopyListDataFrom(QAbstractTableModel& target, const QAbstractTableModel& source);

#pragma endregion


#pragma region Properties and Fields

private:
	CharacterModel _model;

#pragma endregion

};

